package com.file.system.tools.sort;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.file.system.entity.sort.BaseSort;
import com.file.system.mapper.system.SystemSortMapper;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;

/**
 * 数据库排序工具
 *
 * @author 靳春晖
 */
@Configuration
public class SortUtil {

    @Autowired
    private SystemSortMapper service;

    public static SortUtil util;

    @PostConstruct
    public void init() {
        util = this;
        util.service = this.service;
    }


    /**
     * 数据新增排序
     *
     * @param data       排序对象
     * @param clazz      序列化class
     * @param tableName  排序表名
     * @param conditions 排序条件组
     * @return <T> 返回排序对象
     * @author 靳春晖
     */
    public synchronized <T> T add(Object data, Class<T> clazz, String tableName, BaseSort... conditions) {
        // 将参数转换为map
        Map<String, Object> map = BeanUtil.beanToMap(data);
        // 获取排序值
        int sort = Integer.parseInt(map.get("sort").toString());

        //排序
        QueryWrapper sortQueryWrapper = wrapper(conditions);

        sort = setSortAdd(tableName, sort, sortQueryWrapper);
        //添加排序
        boolean flag = addSort(tableName, sort, sortQueryWrapper);
        //排序失败
        if (!flag) return null;
        //获取排序成功后的实体对象
        T t = getObj(clazz, map, sort);
        //赋值失败
        if (ObjectUtil.isNull(t)) return null;
        return t;
    }


    /**
     * 数据编辑排序
     *
     * @param data       排序对象
     * @param clazz      序列化class
     * @param oldSort    旧排序值
     * @param tableName  排序表名
     * @param conditions 排序条件组
     * @return <T> 返回排序对象
     * @author 靳春晖
     */
    public synchronized <T> T update(Object data, Class<T> clazz, int oldSort, String tableName, BaseSort... conditions) {
        // 将参数转换为map
        Map<String, Object> map = BeanUtil.beanToMap(data);
        // 获取排序值
        int sort = Integer.parseInt(map.get("sort").toString());

        //设计排序条件
        QueryWrapper sortQueryWrapper = wrapper(conditions);

        sort = setSortEdit(tableName, sort, sortQueryWrapper);
        //修改排序
        boolean flag = editSort(tableName, sort, oldSort, sortQueryWrapper);
        if (!flag) return null;
        T t = getObj(clazz, map, sort);
        //赋值失败
        if (ObjectUtil.isNull(t)) return null;
        return t;
    }


    /**
     * 数据删除排序
     *
     * @param data       排序对象
     * @param clazz      序列化class
     * @param tableName  排序表名
     * @param conditions 排序条件组
     * @return <T> 返回排序对象
     * @author 靳春晖
     */
    public synchronized <T> T del(Object data, Class<T> clazz, String tableName, BaseSort... conditions) {
        // 将参数转换为map
        Map<String, Object> map = BeanUtil.beanToMap(data);
        // 获取排序值
        int sort = Integer.parseInt(map.get("sort").toString());

        //排序
        QueryWrapper sortQueryWrapper = wrapper(conditions);
        //添加排序
        boolean flag = deleteSort(tableName, sort, sortQueryWrapper);
        //排序失败
        if (!flag) return null;
        //获取排序成功后的实体对象
        T t = getObj(clazz, map, sort);
        //赋值失败
        if (ObjectUtil.isNull(t)) return null;
        return t;
    }

    /**
     * 拼接排序构造器
     *
     * @param conditions 排序条件组
     * @return QueryWrapper 条件构造器
     * @author 靳春晖
     */
    private QueryWrapper wrapper(BaseSort... conditions) {
        //查询构造器
        QueryWrapper sortQueryWrapper = new QueryWrapper<>();
        //添加排序条件
        for (BaseSort baseSort : conditions) {
            //相等=
            if (ObjectUtil.equal(BaseSort.EQ, baseSort.getCondition())) {
                sortQueryWrapper.eq(baseSort.getField(), baseSort.getSortVal());
            }
            //不等<>
            if (ObjectUtil.equal(BaseSort.NE, baseSort.getCondition())) {
                sortQueryWrapper.ne(baseSort.getField(), baseSort.getSortVal());
            }
            //大于>
            if (ObjectUtil.equal(BaseSort.GT, baseSort.getCondition())) {
                sortQueryWrapper.gt(baseSort.getField(), baseSort.getSortVal());
            }
            //大于等于 >=
            if (ObjectUtil.equal(BaseSort.GE, baseSort.getCondition())) {
                sortQueryWrapper.ge(baseSort.getField(), baseSort.getSortVal());
            }
            //小于 <
            if (ObjectUtil.equal(BaseSort.LT, baseSort.getCondition())) {
                sortQueryWrapper.lt(baseSort.getField(), baseSort.getSortVal());
            }
            //小于等于 <=
            if (ObjectUtil.equal(BaseSort.LE, baseSort.getCondition())) {
                sortQueryWrapper.le(baseSort.getField(), baseSort.getSortVal());
            }
        }
        return sortQueryWrapper;
    }


    /**
     * 获取排序成功后的实体对象
     *
     * @param
     * @return
     * @apiNote
     * @author 靳春晖
     * @since
     */
    private <T> T getObj(Class<T> clazz, Map<String, Object> map, int sort) {
        try {
            // 使用newInstance来创建对象
            T obj = clazz.newInstance();
            for (Field field : ReflectUtil.getFields(obj.getClass())) {
                int mod = field.getModifiers();
                // 判断是拥有某个修饰符
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                    continue;
                }
                // 当字段使用private修饰时，需要加上
                field.setAccessible(true);
                // 给obj的属性赋值
                if (ObjectUtil.isNull(map.get(field.getName()))) {
                    continue;
                }
                // 赋值排序字段
                if (field.getName().contains("sort")) {
                    field.set(obj, sort);
                    continue;
                }
                Object val = map.get(field.getName());
                field.set(obj, val);
            }
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 获取新增排序排序值
     *
     * @param tableName        表名
     * @param sort             当前排序值
     * @param sortQueryWrapper mybtais-plus查询器
     * @return int
     * @author 靳春晖
     */
    private int setSortAdd(String tableName, int sort, QueryWrapper<T> sortQueryWrapper) {
        int maxSort = util.service.selectMaxSort(tableName, sortQueryWrapper);
        sort = sort <= 0 ? 1 : sort;
        sort = sort > maxSort ? maxSort + 1 : sort;
        return sort;
    }


    /**
     * 获取修改排序排序值
     *
     * @param tableName        表名
     * @param sort             当前排序值
     * @param sortQueryWrapper mybtais-plus查询器
     * @return int
     * @author 靳春晖
     */
    private int setSortEdit(String tableName, int sort, QueryWrapper<T> sortQueryWrapper) {
        int maxSort = util.service.selectMaxSort(tableName, sortQueryWrapper);
        sort = sort <= 0 ? 1 : sort;
        sort = sort >= maxSort ? maxSort : sort;
        return sort;
    }

    /**
     * 新增排序
     *
     * @param tableName        表名
     * @param sort             当前排序值
     * @param sortQueryWrapper mybtais-plus查询器
     * @return int
     * @author 靳春晖
     */
    private boolean addSort(String tableName, int sort, QueryWrapper<T> sortQueryWrapper) {
        //查询当前排序最大值
        int maxSort = util.service.selectMaxSort(tableName, sortQueryWrapper);
        if (sort > maxSort) return true;

        int state = 0;
        sortQueryWrapper.le("sort", maxSort);
        //新增排序
        if (sort == 1) {
            sortQueryWrapper.ge("sort", 1);
            state = util.service.updateSortAdd(tableName, sortQueryWrapper);
        } else if (sort == maxSort) {
            sortQueryWrapper.ge("sort", maxSort);
            state = util.service.updateSortAdd(tableName, sortQueryWrapper);
        } else {
            sortQueryWrapper.ge("sort", sort);
            state = util.service.updateSortAdd(tableName, sortQueryWrapper);
        }
        if (state < 0) return false;
        return true;
    }

    /**
     * 编辑排序
     *
     * @param tableName        表名
     * @param sort             当前排序值
     * @param sortQueryWrapper mybtais-plus查询器
     * @return int
     * @author 靳春晖
     */
    private boolean editSort(String tableName, int sort, int oldSort, QueryWrapper<T> sortQueryWrapper) {
        //无变化时不处理
        if (sort == oldSort) return true;

        int state = 0;
        if (sort > oldSort) {
            sortQueryWrapper.ge("sort", oldSort);
            sortQueryWrapper.le("sort", sort);
            state = util.service.updateSortReduce(tableName, sortQueryWrapper);
        } else {
            sortQueryWrapper.le("sort", oldSort);
            sortQueryWrapper.ge("sort", sort);
            state = util.service.updateSortAdd(tableName, sortQueryWrapper);
        }
        if (state < 0) return false;
        return true;
    }

    /**
     * 删除排序
     *
     * @param tableName        表名
     * @param sort             当前排序值
     * @param sortQueryWrapper mybtais-plus查询器
     * @return int
     * @author 靳春晖
     */
    private boolean deleteSort(String tableName, int sort, QueryWrapper<T> sortQueryWrapper) {
        //查询当前排序最大值
        int maxSort = util.service.selectMaxSort(tableName, sortQueryWrapper);
        if (sort == maxSort) return true;

        sortQueryWrapper.ge("sort", sort);
        sortQueryWrapper.le("sort", maxSort);
        int state = util.service.updateSortReduce(tableName, sortQueryWrapper);

        if (state < 0) return false;
        return true;
    }
}
